package com.xbongbong.workflow.upgrade;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.executor.command.FormDataServiceFactory;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.config.enums.WorkflowTaskLogStatusEnum;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTaskEntity;
import com.xbongbong.paas.domain.entity.PaasUserEntity;
import com.xbongbong.paas.domain.entity.ext.PaasCommentEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessNodeTaskEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.model.PaasCommentModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasProcessDataMigrateModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.model.PaasProcessMigrationModel;
import com.xbongbong.paas.model.PaasProcessNodeTaskModel;
import com.xbongbong.paas.model.PaasProcessTaskModel;
import com.xbongbong.paas.model.PaasUserModel;
import com.xbongbong.paas.pojo.dto.FixDataJobDTO;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.parent.interfaces.FormDataService;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.domain.entity.PaasProcessDataMigrateEntity;
import com.xbongbong.pro.domain.entity.PaasProcessMigrationEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.formdata.pojo.vo.BeforeSaveVO;
import com.xbongbong.pro.formdata.pojo.vo.SaveVO;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.AssembleProductEntity;
import com.xbongbong.saas.domain.entity.BomProductEntity;
import com.xbongbong.saas.domain.entity.BomUserEntity;
import com.xbongbong.saas.domain.entity.ClueUserEntity;
import com.xbongbong.saas.domain.entity.ContactUserEntity;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.ContractUserEntity;
import com.xbongbong.saas.domain.entity.CustomerUserEntity;
import com.xbongbong.saas.domain.entity.FundTransferEntity;
import com.xbongbong.saas.domain.entity.InventoryProductEntity;
import com.xbongbong.saas.domain.entity.MarketActivityUserEntity;
import com.xbongbong.saas.domain.entity.OpportunityProductEntity;
import com.xbongbong.saas.domain.entity.OpportunityUserEntity;
import com.xbongbong.saas.domain.entity.OtherExpenseEntity;
import com.xbongbong.saas.domain.entity.OtherIncomeEntity;
import com.xbongbong.saas.domain.entity.PayPlanSheetUserEntity;
import com.xbongbong.saas.domain.entity.PaymentSheetUserEntity;
import com.xbongbong.saas.domain.entity.ProductionOrderProductEntity;
import com.xbongbong.saas.domain.entity.ProductionOrderUserEntity;
import com.xbongbong.saas.domain.entity.PurchaseProductEntity;
import com.xbongbong.saas.domain.entity.PurchaseUserEntity;
import com.xbongbong.saas.domain.entity.QuotationProductEntity;
import com.xbongbong.saas.domain.entity.QuotationUserEntity;
import com.xbongbong.saas.domain.entity.RefundUserEntity;
import com.xbongbong.saas.domain.entity.ReturnedPurchaseProductEntity;
import com.xbongbong.saas.domain.entity.SupplierContactUserEntity;
import com.xbongbong.saas.domain.entity.SupplierProductEntity;
import com.xbongbong.saas.domain.entity.SupplierUserEntity;
import com.xbongbong.saas.domain.entity.TransferProductEntity;
import com.xbongbong.saas.domain.entity.WarehouseUserEntity;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFlowUserEntity;
import com.xbongbong.saas.domain.entity.WorkOrderProductEntity;
import com.xbongbong.saas.domain.entity.ext.AssembleEntityExt;
import com.xbongbong.saas.domain.entity.ext.BomBillEntityExt;
import com.xbongbong.saas.domain.entity.ext.ClueEntityExt;
import com.xbongbong.saas.domain.entity.ext.ContactEntityExt;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.domain.entity.ext.InstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.InventoryEntityExt;
import com.xbongbong.saas.domain.entity.ext.InvoiceEntityExt;
import com.xbongbong.saas.domain.entity.ext.MarketActivityEntityExt;
import com.xbongbong.saas.domain.entity.ext.OpportunityEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.PayPlanSheetEntityExt;
import com.xbongbong.saas.domain.entity.ext.PaymentSheetEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductionOrderEntityExt;
import com.xbongbong.saas.domain.entity.ext.PurchaseEntityExt;
import com.xbongbong.saas.domain.entity.ext.PurchaseInvoiceEntityExt;
import com.xbongbong.saas.domain.entity.ext.QuotationEntityExt;
import com.xbongbong.saas.domain.entity.ext.RefundEntityExt;
import com.xbongbong.saas.domain.entity.ext.ReturnedPurchaseEntityExt;
import com.xbongbong.saas.domain.entity.ext.SupplierCommunicateEntityExt;
import com.xbongbong.saas.domain.entity.ext.SupplierContactEntityExt;
import com.xbongbong.saas.domain.entity.ext.SupplierEntityExt;
import com.xbongbong.saas.domain.entity.ext.TransferEntityExt;
import com.xbongbong.saas.domain.entity.ext.WarehouseEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.BusinessCommentEnum;
import com.xbongbong.saas.enums.WorkOrderStatusEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.AssembleModel;
import com.xbongbong.saas.model.AssembleProductModel;
import com.xbongbong.saas.model.BomBillModel;
import com.xbongbong.saas.model.BomProductModel;
import com.xbongbong.saas.model.BomUserModel;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.ClueUserModel;
import com.xbongbong.saas.model.ContactModel;
import com.xbongbong.saas.model.ContactUserModel;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.ContractUserModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.FundTransferModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.InventoryModel;
import com.xbongbong.saas.model.InventoryProductModel;
import com.xbongbong.saas.model.InvoiceModel;
import com.xbongbong.saas.model.MarketActivityModel;
import com.xbongbong.saas.model.MarketActivityUserModel;
import com.xbongbong.saas.model.OpportunityModel;
import com.xbongbong.saas.model.OpportunityProductModel;
import com.xbongbong.saas.model.OpportunityUserModel;
import com.xbongbong.saas.model.OtherExpenseModel;
import com.xbongbong.saas.model.OtherIncomeModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.saas.model.PayPlanSheetModel;
import com.xbongbong.saas.model.PayPlanSheetUserModel;
import com.xbongbong.saas.model.PaymentSheetModel;
import com.xbongbong.saas.model.PaymentSheetUserModel;
import com.xbongbong.saas.model.ProductionOrderModel;
import com.xbongbong.saas.model.ProductionOrderProductModel;
import com.xbongbong.saas.model.ProductionOrderUserModel;
import com.xbongbong.saas.model.PurchaseInvoiceModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.PurchaseProductModel;
import com.xbongbong.saas.model.PurchaseUserModel;
import com.xbongbong.saas.model.QuotationModel;
import com.xbongbong.saas.model.QuotationProductModel;
import com.xbongbong.saas.model.QuotationUserModel;
import com.xbongbong.saas.model.RefundModel;
import com.xbongbong.saas.model.RefundUserModel;
import com.xbongbong.saas.model.ReturnedPurchaseModel;
import com.xbongbong.saas.model.ReturnedPurchaseProductModel;
import com.xbongbong.saas.model.SupplierCommunicateModel;
import com.xbongbong.saas.model.SupplierContactModel;
import com.xbongbong.saas.model.SupplierContactUserModel;
import com.xbongbong.saas.model.SupplierModel;
import com.xbongbong.saas.model.SupplierProductModel;
import com.xbongbong.saas.model.SupplierUserModel;
import com.xbongbong.saas.model.TransferModel;
import com.xbongbong.saas.model.TransferProductModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.model.WarehouseUserModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFlowUserModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.saas.model.WorkOrderProductModel;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.domain.entity.WorkflowCommentEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskLogEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskLogItemEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTransferDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.model.WorkflowCommentModel;
import com.xbongbong.workflow.model.WorkflowTaskLogItemModel;
import com.xbongbong.workflow.model.WorkflowTaskLogModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTaskNodeModel;
import com.xbongbong.workflow.model.WorkflowTransferDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 工作流流转审批数据迁移工具类
 * @author 魏荣杰
 *
 */
@Component
@Slf4j
public class WorkflowDataUpgradeHelp {

    @Resource
    private PaasProcessTaskModel paasProcessTaskModel;
    @Resource
    private PaasProcessNodeTaskModel paasProcessNodeTaskModel;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private WorkflowTaskNodeModel workflowTaskNodeModel;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private WorkflowTransferDataModel workflowTransferDataModel;
    @Resource
    private UserModel userModel;
    @Resource
    private FormDataServiceFactory formDataServiceFactory;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private WorkOrderProductModel workOrderProductModel;
    @Resource
    private WorkOrderFlowUserModel workOrderFlowUserModel;
    @Resource
    private AssembleModel assembleModel;
    @Resource
    private AssembleProductModel assembleProductModel;
    @Resource
    private BomBillModel bomBillModel;
    @Resource
    private BomProductModel bomProductModel;
    @Resource
    private BomUserModel bomUserModel;
    @Resource
    private ClueModel clueModel;
    @Resource
    private ClueUserModel clueUserModel;
    @Resource
    private ContactModel contactModel;
    @Resource
    private ContactUserModel contactUserModel;
    @Resource
    private ContractModel contractModel;
    @Resource
    private ContractUserModel contractUserModel;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private FundTransferModel fundTransferModel;
    @Resource
    private InstockModel instockModel;
    @Resource
    private InventoryModel inventoryModel;
    @Resource
    private InventoryProductModel inventoryProductModel;
    @Resource
    private InvoiceModel invoiceModel;
    @Resource
    private MarketActivityModel marketActivityModel;
    @Resource
    private MarketActivityUserModel marketActivityUserModel;
    @Resource
    private OpportunityModel opportunityModel;
    @Resource
    private OpportunityUserModel opportunityUserModel;
    @Resource
    private OpportunityProductModel opportunityProductModel;
    @Resource
    private OtherExpenseModel otherExpenseModel;
    @Resource
    private OtherIncomeModel otherIncomeModel;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private PaasFormDataModel paasFormDataModel;
    @Resource
    private PaymentSheetModel paymentSheetModel;
    @Resource
    private PayPlanSheetModel payPlanSheetModel;
    @Resource
    private ProductionOrderModel productionOrderModel;
    @Resource
    private ProductionOrderProductModel productionOrderProductModel;
    @Resource
    private ProductionOrderUserModel productionOrderUserModel;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private PurchaseUserModel purchaseUserModel;
    @Resource
    private PurchaseProductModel purchaseProductModel;
    @Resource
    private PurchaseInvoiceModel purchaseInvoiceModel;
    @Resource
    private QuotationModel quotationModel;
    @Resource
    private QuotationUserModel quotationUserModel;
    @Resource
    private QuotationProductModel quotationProductModel;
    @Resource
    private RefundModel refundModel;
    @Resource
    private RefundUserModel refundUserModel;
    @Resource
    private ReturnedPurchaseModel returnedPurchaseModel;
    @Resource
    private ReturnedPurchaseProductModel returnedPurchaseProductModel;
    @Resource
    private SupplierCommunicateModel supplierCommunicateModel;
    @Resource
    private SupplierContactModel supplierContactModel;
    @Resource
    private SupplierContactUserModel supplierContactUserModel;
    @Resource
    private SupplierModel supplierModel;
    @Resource
    private SupplierUserModel supplierUserModel;
    @Resource
    private SupplierProductModel supplierProductModel;
    @Resource
    private TransferModel transferModel;
    @Resource
    private TransferProductModel transferProductModel;
    @Resource
    private WarehouseModel warehouseModel;
    @Resource
    private WarehouseUserModel warehouseUserModel;
    @Resource
    private WorkflowTaskLogModel workflowTaskLogModel;
    @Resource
    private WorkflowTaskLogItemModel workflowTaskLogItemModel;
    @Resource
    private PaasProcessDataMigrateModel paasProcessDataMigrateModel;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private PaymentSheetUserModel paymentSheetUserModel;
    @Resource
    private PayPlanSheetUserModel payPlanSheetUserModel;
    @Resource
    private PaasProcessMigrationModel paasProcessMigrationModel;
    @Resource
    private PaasCommentModel paasCommentModel;
    @Resource
    private WorkflowCommentModel workflowCommentModel;
    @Resource
    private PaasUserModel paasUserModel;


    public void upgradeWorkflowData(FixDataJobDTO fixDataJobDTO) throws XbbException {
        String corpid = fixDataJobDTO.getCorpid();
        List<Long> dataIdList = fixDataJobDTO.getDataIdList();
        Long addTimeStart = fixDataJobDTO.getAddTimeStart();
        List<Integer> businessTypeList = fixDataJobDTO.getBusinessTypeList();
        // 1 为只迁移进行中带审批的，0所有
        Integer type = fixDataJobDTO.getType();

        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        if (CollectionsUtil.isNotEmpty(businessTypeList)) {
            for (Integer businessType : businessTypeList) {
                param.put("businessType", businessType);
                log.warn(XbbRefTypeEnum.getByCode(businessType).getName() + "开始迁移, businessType= " + businessType);
                List<PaasProcessMigrationEntity> paasProcessMigrationEntities = paasProcessMigrationModel.findEntitys(param);
                for (PaasProcessMigrationEntity paasProcessMigrationEntity : paasProcessMigrationEntities) {
                    JSONObject nodeMap = paasProcessMigrationEntity.getNodeMap();
                    Map<Long, Long> longMap = JSONObject.parseObject(nodeMap.toJSONString(), new TypeReference<Map<Long, Long>>(){});
                    upgradeApprovalBusiness(corpid, paasProcessMigrationEntity.getTemplateId(), paasProcessMigrationEntity.getWorkflowId(), longMap, addTimeStart, type);
                }
            }

        } else {
            param.put("templateIdIn", dataIdList);
            List<PaasProcessMigrationEntity> paasProcessMigrationEntities = paasProcessMigrationModel.findEntitys(param);
            for (PaasProcessMigrationEntity paasProcessMigrationEntity : paasProcessMigrationEntities) {
                JSONObject nodeMap = paasProcessMigrationEntity.getNodeMap();
                Map<Long, Long> longMap = JSONObject.parseObject(nodeMap.toJSONString(), new TypeReference<Map<Long, Long>>(){});
                upgradeApprovalBusiness(corpid, paasProcessMigrationEntity.getTemplateId(), paasProcessMigrationEntity.getWorkflowId(), longMap, addTimeStart, type);
            }
        }

        log.warn("工作流数据迁移结束，success");

    }
    /**
     * Description: 工作流数据迁移
     * @param corpid 公司id
	 * @param templateId 审批模板id
	 * @param workflowId 工作流id
     * @param processNodeAndWorkflowNodeMap 以审批节点id为key，工作流节点id为value的集合
     * @param addTimeStart
     * @param type
     * @return void
     * @throws 
     * @author 魏荣杰
     * @date 2021/9/27 10:09
     * @since
     */
    public void upgradeApprovalBusiness(String corpid, Long templateId, Long workflowId, Map<Long, Long> processNodeAndWorkflowNodeMap, Long addTimeStart, Integer type) throws XbbException {
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("templateId", templateId);
        param.put("start", 0);
        param.put("pageNum", 100);
        param.put("orderByStr", "id");
        if (Objects.equals(type, 1)) {
            param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
        } else if (Objects.equals(type, 2)) {
            param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType(), FlowStatusEnum.REJECT.getType(), FlowStatusEnum.REFUSE.getType(), FlowStatusEnum.REVOKE.getType()));
        }
        if (Objects.nonNull(addTimeStart)) {
            param.put("addTimeStart", addTimeStart);
        }

        Long idGte = 0L;

        Integer entitysCount = paasProcessTaskModel.getEntitysCount(param);
        log.warn("模板 templateId= " + templateId + "的审批数据开始迁移， total=" + entitysCount);
        Long count = 0L;
        while (true) {
            param.put("idGte", idGte);

            List<PaasProcessTaskEntity> paasProcessTaskEntities = paasProcessTaskModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(paasProcessTaskEntities)) {
                break;
            }
            count = count + paasProcessTaskEntities.size();
            log.warn("模板 templateId= " + templateId + "的审批数据迁移中， total=" + entitysCount + ", 已迁移 count = " + count);
            idGte = paasProcessTaskEntities.get(paasProcessTaskEntities.size() - 1).getId();

            Set<Long> taskIds = new HashSet<>();
            Set<Long> formIds = new HashSet<>();
            Set<Long> workorderFormIds = new HashSet<>();
            Set<String> createUserIds = new HashSet<>();
            paasProcessTaskEntities.forEach(v -> {
                createUserIds.add(v.getCreatorId());
                taskIds.add(v.getId());
                if (Objects.equals(v.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                    workorderFormIds.add(v.getFormId());
                } else {
                    formIds.add(v.getFormId());
                }
            });

            Map<String, String> createUserIdAndNameMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(createUserIds)) {
                List<UserEntity> userEntities = userModel.getByUserIdIn(corpid, createUserIds, false);
                userEntities.forEach(v -> createUserIdAndNameMap.put(v.getUserId(), v.getName()));
            }

            Map<Long, String> formFormIdAndExplainMap = new HashMap<>();
            Map<Long, PaasFormEntityExt> formEntityExtMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(formIds)) {
                List<PaasFormExplainEntity> paasFormExplainEntities = paasFormExplainModel.getByFormIdIn(formIds, corpid);
                paasFormExplainEntities.forEach(v -> formFormIdAndExplainMap.put(v.getFormId(), v.getExplains()));

                List<PaasFormEntityExt> paasFormEntityExts = paasFormModel.getByIdIn(formIds, corpid);
                paasFormEntityExts.forEach(v -> formEntityExtMap.put(v.getId(), v));
            }

            Map<Long, String> workorderFormIdAndExplainMap = new HashMap<>();
            Map<Long, WorkOrderFormEntityExt> workOrderFormEntityMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(workorderFormIds)) {
                List<WorkOrderExplainEntity> workOrderExplainEntities = workOrderExplainModel.getByFormIdIn(workorderFormIds, corpid);
                workOrderExplainEntities.forEach(v -> workorderFormIdAndExplainMap.put(v.getFormId(), v.getExplains()));

                List<WorkOrderFormEntityExt> workOrderFormEntityExts = workOrderFormModel.getByIdIn(workorderFormIds, corpid);
                workOrderFormEntityExts.forEach(v -> workOrderFormEntityMap.put(v.getId(), v));
            }


            Map<String, Object> params = new HashMap<>();
            params.put(ParameterConstant.CORPID, corpid);
            params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());

            params.put("taskIdIn", taskIds);
            params.put("orderByStr", "id , add_time");
            List<PaasProcessNodeTaskEntityExt> paasProcessNodeTaskEntityExts = paasProcessNodeTaskModel.findEntitys(params);

            // 封装task和node的关系map
            Map<Long, List<PaasProcessNodeTaskEntityExt>> taskAndNodeMap = new HashMap<>();
            paasProcessNodeTaskEntityExts.forEach(v -> taskAndNodeMap.computeIfAbsent(v.getTaskId(),  x -> new ArrayList<>()).add(v));


            // 节点排序
//            taskAndNodeMap.forEach((key, value) -> {
//                value = value.stream().sorted(Comparator.comparingLong(PaasProcessNodeTaskEntityExt::getAddTime)).collect(Collectors.toList());
//                taskAndNodeMap.put(key, value);
//            });


            // 上下文处理
            params.clear();
            params.put(ParameterConstant.CORPID, corpid);
            params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            params.put("taskIdIn", taskIds);
            List<PaasProcessDataEntity> paasProcessDataEntities = paasProcessDataModel.list(params);

            Map<Long, PaasProcessDataEntity> oldTaskIdAndProcessDataMap = new HashMap<>();
            paasProcessDataEntities.forEach(v -> oldTaskIdAndProcessDataMap.put(v.getTaskId(), v));

            Map<Long, Long> taskOldIdAndDataIdMap = new HashMap<>();
            // 审批主表数据备份
            List<PaasProcessDataMigrateEntity> processDataMigrateEntityList = new ArrayList<>();

            for (PaasProcessDataEntity paasProcessDataEntity : paasProcessDataEntities) {
                WorkflowOperateEnum operate = (Objects.equals(paasProcessDataEntity.getFormDataId(), 0L) && Objects.nonNull(paasProcessDataEntity.getFormDataId())) ? WorkflowOperateEnum.ADD : WorkflowOperateEnum.UPDATE;
                if (Objects.equals(operate, WorkflowOperateEnum.ADD)) {
                    // 新建的数据需要做主表数据的插入, 插入后的数据要去修改workflowTaskEntity的dataId
                    FormDataService formDataService = formDataServiceFactory.getFormDataService(paasProcessDataEntity.getBusinessType(), paasProcessDataEntity.getSaasMark());

                    UserEntity userEntity = userModel.getByKeyIngoreDel(paasProcessDataEntity.getCreatorId(), corpid);
                    UserVO userVO = new UserVO();
                    BeanUtil.copyProperties(userEntity, userVO);

                    FormDataAddDTO formDataSaveDTO = new FormDataAddDTO(paasProcessDataEntity.getFormId(), paasProcessDataEntity.getAppId(), paasProcessDataEntity.getMenuId(), JSON.parseObject(paasProcessDataEntity.getData()), paasProcessDataEntity.getSaasMark(), paasProcessDataEntity.getBusinessType(), userVO, paasProcessDataEntity.getCorpid(), null);

                    SaasNeedRedundantAttrPojo saasNeedPojo = JSONObject.parseObject(paasProcessDataEntity.getSaasNeedPoJo(), SaasNeedRedundantAttrPojo.class);
                    formDataSaveDTO.setSaasNeedRedundantAttrPoJo(saasNeedPojo);

                    BeforeSaveVO beforeSaveVO = new BeforeSaveVO();
                    if (Objects.equals(paasProcessDataEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                        // 工单
                        String explains = workorderFormIdAndExplainMap.get(paasProcessDataEntity.getFormId());
                        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, null);
                        List<FieldAttrEntity> explainList = JSON.parseArray(explains, FieldAttrEntity.class);
                        WorkOrderEntity workOrderEntity = new WorkOrderEntity();
                        BeanUtil.copyProperties(paasProcessDataEntity, workOrderEntity);

                        workOrderEntity.setData(JSON.parseObject(paasProcessDataEntity.getData()));
                        workOrderEntity.setId(null);
                        workOrderEntity.setDataId(null);
                        workOrderEntity.setStatus(WorkOrderStatusEnum.UNACCEPTED.getCode());
                        WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormEntityMap.get(paasProcessDataEntity.getFormId());
                        workOrderEntity.setTemplateId(workOrderFormEntityExt.getTemplateId());
                        beforeSaveVO = new BeforeSaveVO(explainMap, explainList, saasNeedPojo, 0, workOrderFormEntityExt, workOrderEntity);
                        PaasProcessDataMigrateEntity paasProcessDataMigrateEntity;
                        Long dataId = 0L;
                        String reason = "";
                        try {
                            SaveVO saveVO = formDataService.saveForWorkflow(formDataSaveDTO, beforeSaveVO, workOrderFormEntityExt, workOrderEntity);
                            dataId = saveVO.getDataId();

                            FormDataAddVO formDataSaveVO = formDataService.afterSaveForWorkflow(formDataSaveDTO, beforeSaveVO, saveVO, workOrderFormEntityExt, workOrderEntity);
                            // taskId 和 dataId绑定
                            taskOldIdAndDataIdMap.put(paasProcessDataEntity.getTaskId(), formDataSaveVO.getFormDataId());

                        } catch (Exception e) {
                            log.error("新建的审批数据入主表数据库失败", e);
                            if (e.getMessage().length() >= 100) {
                                reason = e.getMessage().substring(0,99);
                            } else {
                                reason = e.getMessage();
                            }
                        } finally {
                            // 这边先放老的taskid作为workflowtaskid，后面更新
                            paasProcessDataMigrateEntity = new PaasProcessDataMigrateEntity(corpid, paasProcessDataEntity.getFormId(), paasProcessDataEntity.getSaasMark(), paasProcessDataEntity.getBusinessType(), paasProcessDataEntity.getId(), templateId, paasProcessDataEntity.getTaskId(), workflowId,  dataId, WorkflowOperateEnum.ADD.getType(), reason, DateTimeUtil.getInt(),DelEnum.NORMAL.getDel());
                            processDataMigrateEntityList.add(paasProcessDataMigrateEntity);
                        }
                    } else {
                        String explains = formFormIdAndExplainMap.get(paasProcessDataEntity.getFormId());
                        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, null);
                        List<FieldAttrEntity> explainList = JSON.parseArray(explains, FieldAttrEntity.class);
                        beforeSaveVO = new BeforeSaveVO(explainMap, explainList, saasNeedPojo, 0, null, null);

                        PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
                        BeanUtil.copyProperties(paasProcessDataEntity, paasFormDataEntity);

                        JSONObject dataJsonObj = JSON.parseObject(paasProcessDataEntity.getData());
                        if (dataJsonObj.containsKey("isBringCustomer")) {
                            formDataSaveDTO.setIsBringCustomer(dataJsonObj.getInteger("isBringCustomer"));
                            dataJsonObj.remove("isBringCustomer");
                        }
                        if (dataJsonObj.containsKey("clueId")) {
                            formDataSaveDTO.setClueId(dataJsonObj.getLong("clueId"));
                            dataJsonObj.remove("clueId");
                        }

                        paasFormDataEntity.setData(dataJsonObj);
                        paasFormDataEntity.setId(null);
                        paasFormDataEntity.setDataId(null);
                        beforeSaveVO.setPaasFormDataEntity(paasFormDataEntity);
                        beforeSaveVO.setPaasFormEntityExt(formEntityExtMap.get(paasProcessDataEntity.getFormId()));
                        PaasProcessDataMigrateEntity paasProcessDataMigrateEntity;
                        Long dataId = 0L;
                        String reason = "";
                        try {
                            SaveVO saveVO = formDataService.saveForWorkflow(formDataSaveDTO, beforeSaveVO, beforeSaveVO.getPaasFormEntityExt(), beforeSaveVO.getPaasFormDataEntity());
                            dataId = saveVO.getDataId();

                            FormDataAddVO formDataSaveVO = formDataService.afterSaveForWorkflow(formDataSaveDTO, beforeSaveVO, saveVO, beforeSaveVO.getPaasFormEntityExt(), saveVO.getPaasFormDataEntity());
                            // taskId 和 dataId绑定
                            taskOldIdAndDataIdMap.put(paasProcessDataEntity.getTaskId(), formDataSaveVO.getFormDataId());

                        } catch (Exception e) {
                            log.error("新建的审批数据入主表数据库失败", e);
                            if (e.getMessage().length() >= 100) {
                                reason = e.getMessage().substring(0,99);
                            } else {
                                reason = e.getMessage();
                            }
                        } finally {
                            // 这边先放老的taskid作为workflowtaskid，后面更新
                            paasProcessDataMigrateEntity = new PaasProcessDataMigrateEntity(corpid, paasProcessDataEntity.getFormId(), paasProcessDataEntity.getSaasMark(), paasProcessDataEntity.getBusinessType(), paasProcessDataEntity.getId(), templateId, paasProcessDataEntity.getTaskId(), workflowId,  dataId, WorkflowOperateEnum.ADD.getType(), reason, DateTimeUtil.getInt(),DelEnum.NORMAL.getDel());
                            processDataMigrateEntityList.add(paasProcessDataMigrateEntity);
                        }
                    }

                } else {
                    taskOldIdAndDataIdMap.put(paasProcessDataEntity.getTaskId(), paasProcessDataEntity.getFormDataId());

                    // 这边先放老的taskid作为workflowtaskid，后面更新
                    PaasProcessDataMigrateEntity paasProcessDataMigrateEntity = new PaasProcessDataMigrateEntity(corpid, paasProcessDataEntity.getFormId(), paasProcessDataEntity.getSaasMark(), paasProcessDataEntity.getBusinessType(), paasProcessDataEntity.getId(), templateId, paasProcessDataEntity.getTaskId(), workflowId, paasProcessDataEntity.getFormDataId(), 0 , "", DateTimeUtil.getInt(),DelEnum.NORMAL.getDel());
                    processDataMigrateEntityList.add(paasProcessDataMigrateEntity);

                }
            }

            // 保存迁移的审批中数据，用于还原
            Map<Long, PaasProcessDataMigrateEntity> paasProcessDataMigrateMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(processDataMigrateEntityList)) {
                paasProcessDataMigrateModel.insertBatch(processDataMigrateEntityList);

                processDataMigrateEntityList.forEach(v -> paasProcessDataMigrateMap.put(v.getProcessTaskId(), v));
            }


            Map<Long, Long> taskIdOldAndNewMap = new HashMap<>();
//            Map<Long, Long> nodeOldIdAndNewIdMap = new HashMap<>();
            Map<Long, Long> taskIdAndLogIdMap = new HashMap<>();


            for (PaasProcessTaskEntity paasProcessTaskEntity : paasProcessTaskEntities) {
                // task任务的生成
                Long oldTaskId = paasProcessTaskEntity.getId();
                Long dataId = taskOldIdAndDataIdMap.get(oldTaskId);
                if (Objects.isNull(dataId)) {
                    continue;
                }

                WorkflowTaskEntity workflowTaskEntity = new WorkflowTaskEntity();
                workflowTaskEntity.setCorpid(paasProcessTaskEntity.getCorpid());
                workflowTaskEntity.setAppId(paasProcessTaskEntity.getAppId());
                workflowTaskEntity.setFormId(paasProcessTaskEntity.getFormId());
                workflowTaskEntity.setMenuId(paasProcessTaskEntity.getMenuId());
                workflowTaskEntity.setWorkflowId(workflowId);
                workflowTaskEntity.setDataId(dataId);
                workflowTaskEntity.setSaasMark(paasProcessTaskEntity.getSaasMark());
                workflowTaskEntity.setBusinessType(paasProcessTaskEntity.getBusinessType());
                workflowTaskEntity.setFlowStatus(paasProcessTaskEntity.getFlowStatus());
                workflowTaskEntity.setCreatorId(paasProcessTaskEntity.getCreatorId());
                workflowTaskEntity.setAddTime(paasProcessTaskEntity.getAddTime());
                workflowTaskEntity.setUpdateTime(paasProcessTaskEntity.getUpdateTime());
                workflowTaskEntity.setDel(paasProcessTaskEntity.getDel());
                workflowTaskEntity.setDingtalkProcessInstanceId(paasProcessTaskEntity.getDingtalkProcessInstanceId());
                workflowTaskModel.insert(workflowTaskEntity);

                // 更新工作流流转任务id
                PaasProcessDataMigrateEntity paasProcessDataMigrateEntity = paasProcessDataMigrateMap.get(oldTaskId);
                paasProcessDataMigrateEntity.setWorkflowTaskId(workflowTaskEntity.getId());
                paasProcessDataMigrateModel.update(paasProcessDataMigrateEntity);

                // 工作流日志生成
                WorkflowTaskLogEntity workflowTaskLogEntity = new WorkflowTaskLogEntity();
                workflowTaskLogEntity.setCorpid(corpid);
                workflowTaskLogEntity.setAppId(paasProcessTaskEntity.getAppId());
                workflowTaskLogEntity.setFormId(paasProcessTaskEntity.getFormId());
                workflowTaskLogEntity.setMenuId(paasProcessTaskEntity.getMenuId());
                workflowTaskLogEntity.setSaasMark(paasProcessTaskEntity.getSaasMark());
                workflowTaskLogEntity.setBusinessType(paasProcessTaskEntity.getBusinessType());
                workflowTaskLogEntity.setWorkflowId(workflowId);
                workflowTaskLogEntity.setTaskId(workflowTaskEntity.getId());
                workflowTaskLogEntity.setStatus(getTaskLogStatusByOldTaskFLowStatus(paasProcessTaskEntity.getFlowStatus()));
                workflowTaskLogEntity.setContent("");
                workflowTaskLogEntity.setExitTime(paasProcessTaskEntity.getUpdateTime());
                workflowTaskLogEntity.setAddTime(paasProcessTaskEntity.getAddTime());
                workflowTaskLogEntity.setUpdateTime(paasProcessTaskEntity.getUpdateTime());
                workflowTaskLogEntity.setDel(DelEnum.NORMAL.getDel());

                workflowTaskLogModel.insert(workflowTaskLogEntity);
                taskIdAndLogIdMap.put(workflowTaskEntity.getId(), workflowTaskLogEntity.getId());

                taskIdOldAndNewMap.put(oldTaskId, workflowTaskEntity.getId());

                List<PaasProcessNodeTaskEntityExt> nodes = taskAndNodeMap.get(oldTaskId);

                PaasProcessDataEntity paasProcessDataEntity = oldTaskIdAndProcessDataMap.get(oldTaskId);

                // 当前审批数据节点和节点数据的对应关系（templateNodeId和nodeTask）
                Map<Long, List<PaasProcessNodeTaskEntityExt>> templateNodeIdAndNodeMap = new HashMap<>();
                nodes.forEach(v -> templateNodeIdAndNodeMap.computeIfAbsent(v.getTemplateNodeId(), k -> new ArrayList<>()).add(v));

                Integer businessType = paasProcessTaskEntity.getBusinessType();

                List<WorkflowTaskNodeEntity> taskNodeEntities = new ArrayList<>();
                for (PaasProcessNodeTaskEntityExt node : nodes) {
                    // node节点升级
                    Long sqlDataId = taskOldIdAndDataIdMap.get(node.getTaskId());
                    if (Objects.isNull(sqlDataId)) {
                        continue;
                    }
                    WorkflowTaskNodeEntity workflowTaskNodeEntity = new WorkflowTaskNodeEntity();
                    workflowTaskNodeEntity.setCorpid(node.getCorpid());
                    workflowTaskNodeEntity.setAppId(node.getAppId());
                    workflowTaskNodeEntity.setFormId(node.getFormId());
                    workflowTaskNodeEntity.setMenuId(node.getMenuId());
                    workflowTaskNodeEntity.setSaasMark(paasProcessTaskEntity.getSaasMark());
                    workflowTaskNodeEntity.setBusinessType(paasProcessTaskEntity.getBusinessType());
                    workflowTaskNodeEntity.setWorkflowId(workflowId);
                    workflowTaskNodeEntity.setTaskId(workflowTaskEntity.getId());
                    workflowTaskNodeEntity.setUserId(node.getUserId());
                    workflowTaskNodeEntity.setDataId(sqlDataId);
                    workflowTaskNodeEntity.setTaskType(node.getTaskType());
                    workflowTaskNodeEntity.setSignType(node.getSignType());
                    workflowTaskNodeEntity.setNodeType(node.getNodeType());
                    // 先放老值，后面更新
                    workflowTaskNodeEntity.setLastNodeId(node.getLastNodeId());
                    workflowTaskNodeEntity.setOpinion(node.getOpinion());
                    workflowTaskNodeEntity.setImages(node.getImages());
                    workflowTaskNodeEntity.setAttachment(node.getAttachment());
                    workflowTaskNodeEntity.setTransferUserId(node.getTransferUserId());
                    workflowTaskNodeEntity.setRevokeUserId(node.getRevokeUserId());
                    // TODO: 2021/9/27 这个好像没有用，需要确认（看了一下好像真的没用
                    workflowTaskNodeEntity.setBackspaceNode(0L);
                    workflowTaskNodeEntity.setIsRead(node.getIsRead());
                    workflowTaskNodeEntity.setAddTime(node.getAddTime());
                    workflowTaskNodeEntity.setUpdateTime(node.getUpdateTime());
                    workflowTaskNodeEntity.setDel(node.getDel());
                    workflowTaskNodeEntity.setDingtalkWorkrecordActivityId(node.getDingtalkWorkrecordActivityId());
                    workflowTaskNodeEntity.setDingtalkWorkrecordTaskId(node.getDingtalkWorkrecordTaskId());
                    workflowTaskNodeEntity.setDingtalkProcessInstanceId(node.getDingtalkProcessInstanceId());

                    // 标题用默认规则生成
                    String title;
                    String createUserName = createUserIdAndNameMap.get(paasProcessTaskEntity.getCreatorId());
                    if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                        WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormEntityMap.get(node.getFormId());
                        title = createUserName + I18nMessageUtil.getMessage(CommonConstant.OF) + workOrderFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.APPROVAL);
                    } else {
                        PaasFormEntityExt paasFormEntityExt = formEntityExtMap.get(node.getFormId());
                        title = createUserName + I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.APPROVAL);
                    }
                    workflowTaskNodeEntity.setTitle(title);
                    workflowTaskNodeEntity.setSerialNo(paasProcessDataEntity.getSerialNo());

                    // TODO: 2021/10/26 这个没有，已补，但是怕有问题先留着todo
                    workflowTaskNodeEntity.setLastNodeId(processNodeAndWorkflowNodeMap.getOrDefault(node.getLastNodeId(), 0L));
                    if (processNodeAndWorkflowNodeMap.containsKey(node.getTemplateNodeId())) {
                        workflowTaskNodeEntity.setWorkflowNodeId(processNodeAndWorkflowNodeMap.get(node.getTemplateNodeId()));
                    } else {
                        continue;
                    }

                    taskNodeEntities.add(workflowTaskNodeEntity);
                }
                if (CollectionsUtil.isNotEmpty(taskNodeEntities)) {
                    workflowTaskNodeModel.insertBatch(taskNodeEntities);
//                    nodeOldIdAndNewIdMap = getOldIdAndNewIdMap(nodes, taskNodeEntities);
//                    List<WorkflowTaskNodeEntity> updateList = new ArrayList<>();
//                    if (!nodeOldIdAndNewIdMap.isEmpty()) {
//                        for (WorkflowTaskNodeEntity v : taskNodeEntities) {
//                            if (Objects.nonNull(v.getLastNodeId()) && Objects.equals(v.getLastNodeId(), 0L)) {
//                                if (nodeOldIdAndNewIdMap.containsKey(v.getLastNodeId())) {
//                                    // 更新老值（没有的节点情况置0）
//                                    v.setLastNodeId(nodeOldIdAndNewIdMap.getOrDefault(v.getLastNodeId(), 0L));
//                                    updateList.add(v);
//                                }
//                            }
//                        }
//                    }
//                    if (CollectionsUtil.isNotEmpty(updateList)) {
//                        workflowTaskNodeModel.updateBatch(updateList, corpid);
//                    }
                }


                // 工作流详细日志生成，只生成最后一个节点的日志
                PaasProcessNodeTaskEntityExt lastNodeTask = nodes.get(nodes.size() - 1);
                WorkflowTaskLogItemEntity workflowTaskLogItemEntity = new WorkflowTaskLogItemEntity();
                workflowTaskLogItemEntity.setCorpid(corpid);
                workflowTaskLogItemEntity.setAppId(lastNodeTask.getAppId());
                workflowTaskLogItemEntity.setFormId(lastNodeTask.getFormId());
                workflowTaskLogItemEntity.setMenuId(lastNodeTask.getMenuId());
                workflowTaskLogItemEntity.setSaasMark(paasProcessTaskEntity.getSaasMark());
                workflowTaskLogItemEntity.setBusinessType(paasProcessTaskEntity.getBusinessType());
                workflowTaskLogItemEntity.setWorkflowId(workflowId);
                workflowTaskLogItemEntity.setTaskId(workflowTaskEntity.getId());
                workflowTaskLogItemEntity.setStatus(getTaskLogItemByOldNodeTaskType(lastNodeTask.getTaskType()));
                workflowTaskLogItemEntity.setNodeType(lastNodeTask.getNodeType());
                workflowTaskLogItemEntity.setContent("");
                workflowTaskLogItemEntity.setExitTime(lastNodeTask.getUpdateTime());
                workflowTaskLogItemEntity.setWorkflowNodeId(processNodeAndWorkflowNodeMap.get(lastNodeTask.getTemplateNodeId()));
                workflowTaskLogItemEntity.setAddTime(lastNodeTask.getAddTime());
                workflowTaskLogItemEntity.setUpdateTime(lastNodeTask.getUpdateTime());
                workflowTaskLogItemEntity.setDel(DelEnum.NORMAL.getDel());
                workflowTaskLogItemEntity.setWorkflowTaskLogId(workflowTaskLogEntity.getId());

                workflowTaskLogItemModel.insert(workflowTaskLogItemEntity);

            }


            Set<String> userIds = new HashSet<>();
            paasProcessDataEntities.forEach(v -> userIds.add(v.getCreatorId()));
            params.clear();
            params.put(ParameterConstant.CORPID, corpid);
            params.put("userIdIn", userIds);
            List<UserEntity> userEntities = userModel.findEntitys(params);

            Map<String, User> userMap = new HashMap<>();
            userEntities.forEach(v -> {
                User user = new User();
                BeanUtil.copyProperties(v, user);
                userMap.put(v.getUserId(), user);
            });


            List<WorkflowTransferDataEntity> dataList = new ArrayList<>();
            for (PaasProcessDataEntity paasProcessDataEntity : paasProcessDataEntities) {
                Long dataId = taskOldIdAndDataIdMap.get(paasProcessDataEntity.getTaskId());
                if (Objects.isNull(dataId)) {
                    continue;
                }
                WorkflowOperateEnum operate = (Objects.equals(paasProcessDataEntity.getFormDataId(), 0L) && Objects.nonNull(paasProcessDataEntity.getFormDataId())) ? WorkflowOperateEnum.ADD : WorkflowOperateEnum.UPDATE;

                WorkflowBackupDataEntity workflowBackupDataEntity = null;

                JSONObject backupData = new JSONObject();
                if (Objects.equals(operate, WorkflowOperateEnum.ADD)) {
                    // 新建的数据需要做主表数据的插入, 插入后的数据要去修改workflowTaskEntity的dataId
                    // 这边前置插入了，这边不做操作
                } else {
                    // 编辑的数据需要生成 WorkflowBackupDataEntity 备份数据
                    workflowBackupDataEntity = new WorkflowBackupDataEntity();
                    workflowBackupDataEntity.setCorpid(paasProcessDataEntity.getCorpid());
                    workflowBackupDataEntity.setAppId(paasProcessDataEntity.getAppId());
                    workflowBackupDataEntity.setFormId(paasProcessDataEntity.getFormId());
                    workflowBackupDataEntity.setMenuId(paasProcessDataEntity.getMenuId());
                    workflowBackupDataEntity.setWorkflowId(workflowId);
                    workflowBackupDataEntity.setTaskId(taskIdOldAndNewMap.get(paasProcessDataEntity.getTaskId()));
                    workflowBackupDataEntity.setDataId(dataId);
                    Integer businessType = paasProcessDataEntity.getBusinessType();
                    backupData = getBackupData(corpid, dataId, businessType, paasProcessDataEntity.getSaasMark());
                    workflowBackupDataEntity.setData(backupData);
                    workflowBackupDataEntity.setAddTime(paasProcessDataEntity.getAddTime());
                    workflowBackupDataEntity.setUpdateTime(paasProcessDataEntity.getUpdateTime());
                    workflowBackupDataEntity.setDel(paasProcessDataEntity.getDel());

                    workflowBackupDataModel.insert(workflowBackupDataEntity);
                }

                // 上下文升数据处理，升级
                WorkflowTransferDataEntity workflowTransferDataEntity = new WorkflowTransferDataEntity();
                workflowTransferDataEntity.setCorpid(paasProcessDataEntity.getCorpid());
                workflowTransferDataEntity.setWorkflowId(workflowId);

                Long taskId = taskIdOldAndNewMap.get(paasProcessDataEntity.getTaskId());
                workflowTransferDataEntity.setTaskId(taskId);

                // 老的没logid
                workflowTransferDataEntity.setLogId(taskIdAndLogIdMap.get(taskId));

                workflowTransferDataEntity.setSaasNeedPojo(JSON.parseObject(paasProcessDataEntity.getSaasNeedPoJo()));
                workflowTransferDataEntity.setAddTime(paasProcessDataEntity.getAddTime());
                workflowTransferDataEntity.setUpdateTime(paasProcessDataEntity.getUpdateTime());
                workflowTransferDataEntity.setDel(paasProcessDataEntity.getDel());

                Data data = new Data();
                data.setFormId(paasProcessDataEntity.getFormId());
                // TODO: 2021/9/27 老数据的data可能格式有出入
                data.setData(JSON.parseObject(paasProcessDataEntity.getData()));
                data.setAppId(paasProcessDataEntity.getAppId());
                data.setMenuId(paasProcessDataEntity.getMenuId());
                // 这个东西可能老的只有编辑进审批的才有，有出入, 在上面已经把新建进审批的数据的关联关系封装到taskOldIdAndDataIdMap中了
                data.setId(dataId);
                data.setBusinessType(paasProcessDataEntity.getBusinessType());
                data.setSubBusinessType(Objects.isNull(paasProcessDataEntity.getSubBusinessType()) ? paasProcessDataEntity.getBusinessType() : paasProcessDataEntity.getSubBusinessType());
                data.setSaasMark(paasProcessDataEntity.getSaasMark());

                List<PaasProcessNodeTaskEntityExt> nodeTaskEntityExts = taskAndNodeMap.get(paasProcessDataEntity.getTaskId());
                data.setNodeId(processNodeAndWorkflowNodeMap.get(nodeTaskEntityExts.get(0).getId()));

                WorkflowTransferPOJO workflowTransferPOJO = new WorkflowTransferPOJO();
                workflowTransferPOJO.setData(data);
                if (Objects.equals(operate, WorkflowOperateEnum.ADD)) {
                    workflowTransferPOJO.setOldData(null);
                } else {
                    // TODO: 2021/10/26 缺初始节点的id,已补，但是怕有问题先留着todo
                    backupData.remove(StringConstant.PRODUCT);
                    backupData.remove(StringConstant.USER_TEAM);
                    Data oldData = new Data(paasProcessDataEntity.getAppId(), paasProcessDataEntity.getMenuId(), paasProcessDataEntity.getFormId(), dataId, backupData, paasProcessDataEntity.getBusinessType(), paasProcessDataEntity.getSaasMark(), processNodeAndWorkflowNodeMap.get(nodeTaskEntityExts.get(0).getTemplateNodeId()), Objects.isNull(paasProcessDataEntity.getSubBusinessType()) ? paasProcessDataEntity.getBusinessType() : paasProcessDataEntity.getSubBusinessType());
                    workflowTransferPOJO.setOldData(oldData);
                }
                workflowTransferPOJO.setFlowDatas(null);

                String creatorId = paasProcessDataEntity.getCreatorId();
                workflowTransferPOJO.setUser(userMap.get(creatorId));
                workflowTransferPOJO.setTaskId(taskId);
                workflowTransferPOJO.setCorpid(corpid);
                workflowTransferPOJO.setLogId(taskIdAndLogIdMap.getOrDefault(taskId, 0L));


                workflowTransferPOJO.setOperate(operate.getType());
                // 老审批导入不进审批，直接置0
                workflowTransferPOJO.setIsImport(0);
                // 用新插入的backup数据id
                if (Objects.isNull(workflowBackupDataEntity)) {
                    workflowTransferPOJO.setBackupDataId(0L);
                } else {
                    workflowTransferPOJO.setBackupDataId(workflowBackupDataEntity.getId());
                }

                workflowTransferDataEntity.setData(JSON.parseObject(JSON.toJSONString(workflowTransferPOJO, SerializerFeature.DisableCircularReferenceDetect)));
                workflowTransferDataEntity.setFormId(paasProcessDataEntity.getFormId());
                workflowTransferDataEntity.setSaasMark(paasProcessDataEntity.getSaasMark());
                workflowTransferDataEntity.setBusinessType(paasProcessDataEntity.getBusinessType());
                workflowTransferDataEntity.setOperate(operate.getType());
                workflowTransferDataEntity.setDataId(dataId);

                dataList.add(workflowTransferDataEntity);
            }
            if (CollectionsUtil.isNotEmpty(dataList)) {
                workflowTransferDataModel.insertBatch(dataList);
            }

        }




    }

    private JSONObject getBackupData(String corpid, Long dataId, Integer businessType, Integer saasMark) throws XbbException {
        JSONObject data = new JSONObject();
        if (Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode())) {
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            switch (xbbRefTypeEnum) {
                case WORK_ORDER:
                    WorkOrderEntity workOrderEntity = workOrderModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(workOrderEntity.getData(), workOrderEntity);
                    List<WorkOrderProductEntity> workOrderProductEntities = workOrderProductModel.getProductsByWorkOrderId(dataId, corpid);
                    workOrderEntity.getData().put(StringConstant.PRODUCT, workOrderProductEntities);

                    List<WorkOrderFlowUserEntity> userEntityList = workOrderFlowUserModel.getUserListByWorkorderId(corpid, dataId);
                    workOrderEntity.getData().put(StringConstant.USER_TEAM, userEntityList);

                    data = workOrderEntity.getData();
                    break;
                case ASSEMBLE:
                    AssembleEntityExt assembleEntityExt = assembleModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(assembleEntityExt.getData(), assembleEntityExt);
                    List<AssembleProductEntity> productList = assembleProductModel.getProductsByAssembleId(dataId, corpid);
                    assembleEntityExt.getData().put(StringConstant.PRODUCT, productList);

                    data = assembleEntityExt.getData();
                    break;
                case BOM_BILL:
                    BomBillEntityExt bomBillEntityExt = bomBillModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(bomBillEntityExt.getData(), bomBillEntityExt);
                    List<BomProductEntity> bomProductEntityList = bomProductModel.getProductsByBomId(dataId, corpid, null);
                    bomBillEntityExt.getData().put(StringConstant.PRODUCT, bomProductEntityList);
                    List<BomUserEntity> bomUserList = bomUserModel.getBomUserListByBomId(corpid, dataId);
                    bomBillEntityExt.getData().put(StringConstant.USER_TEAM, bomUserList);
                    data = bomBillEntityExt.getData();
                    break;
                case CLUE:
                    ClueEntityExt clueEntityExt = clueModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(clueEntityExt.getData(), clueEntityExt);
                    List<ClueUserEntity> clueUserList = clueUserModel.getClueUserList(corpid, dataId, null);
                    clueEntityExt.getData().put(StringConstant.USER_TEAM, clueUserList);

                    data = clueEntityExt.getData();
                    break;
                case CUSTOMER_COMMUNICATE:
                    break;
                case COMMUNICATE_PLAN:
                    break;
                case CONTACT:
                    ContactEntityExt contactEntityExt = contactModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(contactEntityExt.getData(), contactEntityExt);
                    List<ContactUserEntity> contactList = contactUserModel.getListByContactId(corpid, dataId, null);
                    contactEntityExt.getData().put(StringConstant.USER_TEAM, contactList);

                    data = contactEntityExt.getData();
                    break;
                case CONTRACT:
                    ContractEntityExt contractEntityExt = contractModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(contractEntityExt.getData(), contractEntityExt);
                    List<ContractUserEntity> contractUserList = contractUserModel.getContractUserList(corpid, dataId, null);
                    contractEntityExt.getData().put(StringConstant.USER_TEAM, contractUserList);
                    List<ContractProductEntity> contractProductEntityList = contractProductModel.getProductsByConId(dataId, corpid);
                    contractEntityExt.getData().put(StringConstant.PRODUCT, contractProductEntityList);

                    data = contractEntityExt.getData();
                    break;
                case CUSTOMER:
                case CUSTOMER_MANAGEMENT:
                    CustomerEntityExt customerEntityExt = customerModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(customerEntityExt.getData(), customerEntityExt);
                    List<CustomerUserEntity> customerUserEntityList = customerUserModel.getByCustomerId(corpid, dataId);
                    customerEntityExt.getData().put(StringConstant.USER_TEAM, customerUserEntityList);

                    data = customerEntityExt.getData();
                    break;
                case FUND_TRANSFER:
                    FundTransferEntity fundTransferEntity = fundTransferModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(fundTransferEntity.getData(), fundTransferEntity);

                    data = fundTransferEntity.getData();
                    break;
                case INSTOCK:
                case PURCHASE_INSTOCK:
                case REFUND_INSTOCK:
                case OTHER_INSTOCK:
                case PRODUCTION_INSTOCK:
                case RETURNED_MATERIEL_INSTOCK:
                    InstockEntityExt instockEntityExt = instockModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(instockEntityExt.getData(), instockEntityExt);

                    data = instockEntityExt.getData();
                    break;
                case INVENTORY:
                    InventoryEntityExt inventoryEntityExt = inventoryModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(inventoryEntityExt.getData(), inventoryEntityExt);
                    List<InventoryProductEntity> inventoryProductEntityList = inventoryProductModel.getProductsByInventoryId(dataId, corpid);
                    inventoryEntityExt.getData().put(StringConstant.PRODUCT, inventoryProductEntityList);

                    data = inventoryEntityExt.getData();
                    break;
                case INVOICE:
                    InvoiceEntityExt invoiceEntityExt = invoiceModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(invoiceEntityExt.getData(), invoiceEntityExt);

                    data = invoiceEntityExt.getData();
                    break;
                case MARKET_ACTIVITY:
                    MarketActivityEntityExt marketActivityEntityExt = marketActivityModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(marketActivityEntityExt.getData(), marketActivityEntityExt);
                    List<MarketActivityUserEntity> userTeamList = marketActivityUserModel.getMarketActivityUserList(corpid, dataId, null);
                    marketActivityEntityExt.getData().put(StringConstant.USER_TEAM, userTeamList);

                    data = marketActivityEntityExt.getData();
                    break;
                case SALES_OPPORTUNITY:
                    OpportunityEntityExt opportunityEntityExt = opportunityModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(opportunityEntityExt.getData(), opportunityEntityExt);
                    List<OpportunityUserEntity> opportunityUserList = opportunityUserModel.getOpportunityUserList(corpid, dataId, null);
                    opportunityEntityExt.getData().put(StringConstant.USER_TEAM, opportunityUserList);
                    List<OpportunityProductEntity> opportunityProductEntityList = opportunityProductModel.getProductsByOppId(dataId, corpid);
                    opportunityEntityExt.getData().put(StringConstant.PRODUCT, opportunityProductEntityList);

                    data = opportunityEntityExt.getData();
                    break;
                case OTHER_EXPENSE:
                    OtherExpenseEntity otherExpenseEntity = otherExpenseModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(otherExpenseEntity.getData(), otherExpenseEntity);

                    data = otherExpenseEntity.getData();
                    break;
                case OTHER_INCOME:
                    OtherIncomeEntity otherIncomeEntity = otherIncomeModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(otherIncomeEntity.getData(), otherIncomeEntity);

                    data =otherIncomeEntity.getData();
                    break;
                case OUTSTOCK:
                case CONTRACT_OUTSTOCK:
                case OTHER_OUTSTOCK:
                case RETURNED_PURCHASE_OUTSTOCK:
                case WORK_ORDER_OUTSTOCK:
                case PRODUCTION_MATERIEL_OUTSTOCK:
                    OutstockEntityExt outstockEntityExt = outstockModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(outstockEntityExt.getData(), outstockEntityExt);

                    data = outstockEntityExt.getData();
                    break;
                case PAYMENT:

                    break;
                case PAYMENT_SHEET:
                case WRITE_OFF_PREPAYMENT:
                case PREPAYMENT:
                case RED_PREPAYMENT:
                case RED_PAYMENT_SHEET:
                case RED_WRITE_OFF_PREPAYMENT:
                case RED_WRITE_OFF_BALANCE:
                case BAD_DEBT:
                    PaymentSheetEntityExt paymentSheetEntityExt = paymentSheetModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(paymentSheetEntityExt.getData(), paymentSheetEntityExt);

                    List<PaymentSheetUserEntity> paymentSheetUserIdList = paymentSheetUserModel.getPaymentSheetUserIdList(corpid, dataId, null);
                    data.put(StringConstant.USER_TEAM, paymentSheetUserIdList);

                    data = paymentSheetEntityExt.getData();
                    break;
                case PAY_PLAN:
                    break;
                case PAY_SHEET:
                case WRITE_OFF_PREPAY:
                case RED_WRITE_OFF_PAY:
                case RED_WRITE_OFF_PREPAY:
                case PREPAY:
                case RED_PREPAY:
                case BAD_PAY:
                    PayPlanSheetEntityExt payPlanSheetEntityExt = payPlanSheetModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(payPlanSheetEntityExt.getData(), payPlanSheetEntityExt);

                    List<PayPlanSheetUserEntity> paySheetUserIdList = payPlanSheetUserModel.getPaySheetUserIdList(corpid, dataId, null);
                    data.put(StringConstant.USER_TEAM, paySheetUserIdList);

                    data = payPlanSheetEntityExt.getData();
                    break;
                case PRODUCT:

                    break;
                case PRODUCTION_ORDER:
                    ProductionOrderEntityExt productionOrderEntityExt = productionOrderModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(productionOrderEntityExt.getData(), productionOrderEntityExt);
                    List<ProductionOrderProductEntity> productionOrderProductEntityList = productionOrderProductModel.getProductsById(dataId, corpid, null);
                    productionOrderEntityExt.getData().put(StringConstant.PRODUCT, productionOrderProductEntityList);
                    List<ProductionOrderUserEntity> productionOrderUserEntityList = productionOrderUserModel.getProductionOrderUserListByProductionOrderId(corpid, dataId);
                    productionOrderEntityExt.getData().put(StringConstant.USER_TEAM, productionOrderUserEntityList);

                    data = productionOrderEntityExt.getData();
                    break;
                case PURCHASE:
                    PurchaseEntityExt purchaseEntityExt = purchaseModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(purchaseEntityExt.getData(), purchaseEntityExt);
                    List<PurchaseUserEntity> purchaseUserEntityList = purchaseUserModel.getPurchaseUserListByPurchaseId(corpid, dataId, null);
                    purchaseEntityExt.getData().put(StringConstant.USER_TEAM, purchaseUserEntityList);
                    List<PurchaseProductEntity> purchaseProductEntityList = purchaseProductModel.getProductsByPurchaseId( corpid, dataId);
                    purchaseEntityExt.getData().put(StringConstant.PRODUCT, purchaseProductEntityList);

                    data = purchaseEntityExt.getData();
                    break;
                case PURCHASE_INVOICE:
                    PurchaseInvoiceEntityExt purchaseInvoiceEntityExt = purchaseInvoiceModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(purchaseInvoiceEntityExt.getData(), purchaseInvoiceEntityExt);

                    data = purchaseInvoiceEntityExt.getData();
                    break;
                case QUOTATION:
                    QuotationEntityExt quotationEntityExt = quotationModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(quotationEntityExt.getData(), quotationEntityExt);
                    List<QuotationUserEntity> quotationUserList = quotationUserModel.getQuotationUserList(corpid, dataId, null);
                    quotationEntityExt.getData().put(StringConstant.USER_TEAM, quotationUserList);
                    List<QuotationProductEntity> quotationProductEntityList = quotationProductModel.getProductsByQuoId(dataId, corpid);
                    quotationEntityExt.getData().put(StringConstant.PRODUCT, quotationProductEntityList);

                    data = quotationEntityExt.getData();
                    break;
                case REFUND:
                    RefundEntityExt refundEntityExt = refundModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(refundEntityExt.getData(), refundEntityExt);
                    List<RefundUserEntity> refundUserEntityList = refundUserModel.getByRefundId(corpid, dataId);
                    refundEntityExt.getData().put(StringConstant.USER_TEAM, refundUserEntityList);

                    data = refundEntityExt.getData();
                    break;
                case RETURNED_PURCHASE:
                    ReturnedPurchaseEntityExt returnedPurchaseEntityExt = returnedPurchaseModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(returnedPurchaseEntityExt.getData(), returnedPurchaseEntityExt);
                    List<ReturnedPurchaseProductEntity> returnedPurchaseProductEntityList = returnedPurchaseProductModel.getProductsByRetPurchaseId(corpid, dataId);
                    returnedPurchaseEntityExt.getData().put(StringConstant.PRODUCT, returnedPurchaseProductEntityList);

                    data = returnedPurchaseEntityExt.getData();
                    break;
                case SUPPLIER_COMMUNICATE:
                    SupplierCommunicateEntityExt supplierCommunicateEntityExt = supplierCommunicateModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(supplierCommunicateEntityExt.getData(), supplierCommunicateEntityExt);

                    data = supplierCommunicateEntityExt.getData();
                    break;
                case SUPPLIER_CONTACT:
                    SupplierContactEntityExt supplierContactEntityExt = supplierContactModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(supplierContactEntityExt.getData(), supplierContactEntityExt);
                    List<SupplierContactUserEntity> userEntities = supplierContactUserModel.getBySupplierId(corpid, dataId);
                    supplierContactEntityExt.getData().put(StringConstant.USER_TEAM, userEntities);

                    data = supplierContactEntityExt.getData();
                    break;
                case SUPPLIER:
                    SupplierEntityExt supplierEntityExt = supplierModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(supplierEntityExt.getData(), supplierEntityExt);
                    List<SupplierUserEntity> supplierUserEntityList = supplierUserModel.getSupplierUserListBySupplierId(corpid, dataId);
                    supplierEntityExt.getData().put(StringConstant.USER_TEAM, supplierUserEntityList);

                    List<SupplierProductEntity> supplierProductEntityList = supplierProductModel.getSupplierProductBySupplierId(corpid, dataId);
                    supplierEntityExt.getData().put(StringConstant.PRODUCT, supplierProductEntityList);

                    data = supplierEntityExt.getData();
                    break;
                case TRANSFER:
                    TransferEntityExt transferEntityExt = transferModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(transferEntityExt.getData(), transferEntityExt);
                    List<TransferProductEntity> transferProductEntities = transferProductModel.getProductsByTransferId(dataId, corpid);
                    transferEntityExt.getData().put(StringConstant.PRODUCT, transferProductEntities);

                    data = transferEntityExt.getData();
                    break;
                case WAREHOUSE:
                    WarehouseEntityExt warehouseEntityExt = warehouseModel.getByKey(dataId, corpid);
                    FormDataUtil.setSystemData(warehouseEntityExt.getData(), warehouseEntityExt);
                    List<WarehouseUserEntity> warehouseUserEntities = warehouseUserModel.getUserListByDataId(corpid, dataId);
                    warehouseEntityExt.getData().put(StringConstant.USER_TEAM, warehouseUserEntities);

                    data = warehouseEntityExt.getData();
                    break;
                case WORK_REPORT:
                    break;
                default:
            }
        } else {
            PaasFormDataEntityExt paasFormDataEntityExt = paasFormDataModel.getByKey(dataId, corpid);
            FormDataUtil.setSystemData(paasFormDataEntityExt.getData(), paasFormDataEntityExt);
            List<PaasUserEntity> paasUserList = paasUserModel.getPaasUserList(corpid, dataId, null);
            data.put(StringConstant.USER_TEAM, paasUserList);
            data = paasFormDataEntityExt.getData();
        }

        return data;
    }


    private Map<Long, Long> getOldIdAndNewIdMap(List oldList, List newList) {
        Map<Long, Long> oldIdAndNewIdMap = new HashMap<>();
        try {
            for (int i = 0; i < oldList.size(); i++) {
                Object o = oldList.get(i);
                Method method = o.getClass().getMethod("getId");
                Object invoke = method.invoke(o);

                Object o1 = newList.get(i);
                Method method1 = o1.getClass().getMethod("getId");
                Object invoke1 = method1.invoke(o1);

                oldIdAndNewIdMap.put(Long.valueOf(invoke.toString()), Long.valueOf(invoke1.toString()));
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.upgrade.WorkflowDataUpgradeHelp.getOldIdAndNewIdMap fail", e);
        }
        return oldIdAndNewIdMap;
    }


    private Integer getTaskLogStatusByOldTaskFLowStatus(Integer flowStatus) {
        FlowStatusEnum flowStatusEnum = FlowStatusEnum.getFlowStatusEnumByType(flowStatus);
        switch (flowStatusEnum) {
            case NOT_NEED_APPROVAL:
            case PASS:
                return WorkflowTaskLogStatusEnum.PASS.getType();
            case APPROVAL_PENDING:
            case IN_APPROVAL:
            case REFUSE:
                return WorkflowTaskLogStatusEnum.WAIT.getType();
            case REJECT:
            case REVOKE:
                return WorkflowTaskLogStatusEnum.SUSPEND.getType();
            case ERROR_UNKNOWN:
                return WorkflowTaskLogStatusEnum.UNKNOWN.getType();
            default:
        }
        return WorkflowTaskLogStatusEnum.WAIT.getType();
    }


    private Integer getTaskLogItemByOldNodeTaskType(Integer taskType) {
        TaskTypeEnum taskTypeEnum = TaskTypeEnum.getTaskTypeEnum(taskType);
        switch (taskTypeEnum) {
            case UNTREATED:
            case STORAGE:
                return WorkflowTaskLogStatusEnum.WAIT.getType();
            case COMMIT:
                return WorkflowTaskLogStatusEnum.PASS.getType();
            case TRANSFER:
                return WorkflowTaskLogStatusEnum.WAIT.getType();
            case BACK:
                return WorkflowTaskLogStatusEnum.PASS.getType();
            case END:
                return WorkflowTaskLogStatusEnum.SUSPEND.getType();
            case REVOKE:
                return WorkflowTaskLogStatusEnum.SUSPEND.getType();
            case AGAIN_COMMIT:
                return WorkflowTaskLogStatusEnum.PASS.getType();
            case WAIT_CC:
                return WorkflowTaskLogStatusEnum.WAIT.getType();
            case OTHER_COMMIT:
                // TODO: 2021/10/29
                return WorkflowTaskLogStatusEnum.PASS.getType();
            case SYSTEM_COMMIT:
                // TODO: 2021/10/29
                return WorkflowTaskLogStatusEnum.WAIT.getType();
            case CC:
                // TODO: 2021/10/29
                return WorkflowTaskLogStatusEnum.WAIT.getType();
            case SYSTEM_PASS:
                // TODO: 2021/10/29
                return WorkflowTaskLogStatusEnum.PASS.getType();
            case COMMIT_PRINT:
            case ACTIVATION:
            case PROCESS_COMMENT:
            case ESIGN:
            case PRINT:
                // 这个没
            default:
                break;
        }
        return WorkflowTaskLogStatusEnum.WAIT.getType();
    }


    /**
     * 工作流迁移数据还原
     * @param fixDataJobDTO
     */
    public void upgradeWorkflowDataBack(FixDataJobDTO fixDataJobDTO) throws XbbException {
        String corpid = fixDataJobDTO.getCorpid();
        List<Long> dataIdList = fixDataJobDTO.getDataIdList();
        List<Integer> businessTypeList = fixDataJobDTO.getBusinessTypeList();

        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        if (CollectionsUtil.isNotEmpty(businessTypeList)) {
            for (Integer businessType : businessTypeList) {
                param.put("businessType", businessType);
                log.warn(XbbRefTypeEnum.getByCode(businessType).getName() + "工作流迁移数据开始还原, businessType= " + businessType);
                List<PaasProcessMigrationEntity> paasProcessMigrationEntities = paasProcessMigrationModel.findEntitys(param);
                for (PaasProcessMigrationEntity paasProcessMigrationEntity : paasProcessMigrationEntities) {
                    backApprovalData(corpid, paasProcessMigrationEntity.getTemplateId());
                }
            }

        } else if (CollectionsUtil.isNotEmpty(dataIdList)){
            for (Long aLong : dataIdList) {
                backApprovalData(corpid, aLong);
            }
        }

        log.warn("工作流迁移数据还原结束，success");
    }


    /**
     * Description: 还原审批迁移数据（流转数据+主表数据）
     * @param corpid 公司id
	 * @param templateId 审批模板id
     * @author 魏荣杰
     * @date 2021/11/9 10:54
     */
    public void backApprovalData(String corpid, Long templateId) throws XbbException {
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("templateId", templateId);
        param.put("orderByStr", "id");
        param.put("start", 0);
        param.put("pageNum", 100);
        Long idGte = 0L;

        while (true) {
            param.put("idGte", idGte);
            List<PaasProcessDataMigrateEntity> paasProcessDataMigrateEntities = paasProcessDataMigrateModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(paasProcessDataMigrateEntities)) {
                break;
            }
            idGte = paasProcessDataMigrateEntities.get(paasProcessDataMigrateEntities.size() - 1).getId();

            // 迁移过来的工作流任务id
            List<Long> workflowTaskIds = new ArrayList<>();
            // 新增的需要删除的主表数据的id
            List<Long> addDataIds = new ArrayList<>();
            for (PaasProcessDataMigrateEntity paasProcessDataMigrateEntity : paasProcessDataMigrateEntities) {
                if (!Objects.equals(paasProcessDataMigrateEntity.getWorkflowTaskId(), 0L)) {
                    workflowTaskIds.add(paasProcessDataMigrateEntity.getWorkflowTaskId());
                }
                if (Objects.equals(paasProcessDataMigrateEntity.getType(), WorkflowOperateEnum.ADD.getType()) && !Objects.equals(paasProcessDataMigrateEntity.getDataId(), 0L)) {
                    addDataIds.add(paasProcessDataMigrateEntity.getDataId());
                }
            }

            extracted(corpid, paasProcessDataMigrateEntities.get(0).getSaasMark(), paasProcessDataMigrateEntities.get(0).getBusinessType(), workflowTaskIds, addDataIds);

        }

    }

    private void extracted(String corpid, Integer saasMark, Integer businessType, List<Long> workflowTaskIds, List<Long> addDataIds) throws XbbException {
        if (CollectionsUtil.isNotEmpty(workflowTaskIds)) {
            // 删除task
            workflowTaskModel.deleteByTaskIds(corpid, workflowTaskIds);
            // 删除tasknode
            workflowTaskNodeModel.deleteByTaskIds(corpid, workflowTaskIds);
            // 删除log
            workflowTaskLogModel.deleteByTaskIds(corpid, workflowTaskIds);
            workflowTaskLogItemModel.deleteByTaskIds(corpid, workflowTaskIds);
            // 删除上下文
            workflowTransferDataModel.deleteByTaskIds(corpid, workflowTaskIds);
            // 删除备份表
            workflowBackupDataModel.deleteByTaskIds(corpid, workflowTaskIds);
        }

        // 删除主表数据
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        try {
            if (CollectionsUtil.isNotEmpty(addDataIds)) {
                if (Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode())) {
                    switch (xbbRefTypeEnum) {
                        case ASSEMBLE:
                            assembleModel.deleteBatch(addDataIds, corpid);
                            assembleProductModel.deleteByAssembleIdIn(addDataIds, corpid);
                            break;
                        case BOM_BILL:
                            bomBillModel.deleteBatch(addDataIds, corpid);
                            bomUserModel.deleteByBomIdIn(addDataIds, corpid);
                            bomProductModel.deleteByBomIdIn(addDataIds, corpid);
                            break;
                        case CLUE:
                            clueModel.deleteBatch(addDataIds, corpid);
                            clueUserModel.deleteBatchByClueIdIn(addDataIds, corpid);
                            break;
                        case CUSTOMER_COMMUNICATE:
                            break;
                        case COMMUNICATE_PLAN:
                            break;
                        case CONTACT:
                            contactModel.deleteBatch(addDataIds, corpid);
                            contactUserModel.deleteBatchByContactIdIn(addDataIds, corpid);
                            break;
                        case CONTRACT:
                            contractModel.deleteBatch(addDataIds, corpid);
                            contractUserModel.deleteByContractIdIn(addDataIds, corpid);
                            break;
                        case CUSTOMER:
                        case CUSTOMER_MANAGEMENT:
                            customerModel.deleteBatch(addDataIds, corpid);
                            customerUserModel.batchDeleteByCustomerId(corpid, addDataIds, null);
                            break;
                        case FUND_TRANSFER:
                            fundTransferModel.deleteBatch(addDataIds, corpid);
                            break;
                        case INSTOCK:
                        case PURCHASE_INSTOCK:
                        case REFUND_INSTOCK:
                        case OTHER_INSTOCK:
                        case PRODUCTION_INSTOCK:
                        case RETURNED_MATERIEL_INSTOCK:
                            instockModel.deleteBatch(addDataIds, corpid);
                            instockProductModel.deleteByInstockIdIn(corpid, addDataIds);
                            break;
                        case INVENTORY:
                            inventoryModel.deleteBatch(addDataIds, corpid, 0);
                            inventoryProductModel.deleteByInventoryIdIn(corpid, addDataIds);
                            break;
                        case INVOICE:
                            invoiceModel.deleteBatch(addDataIds, corpid, 0);
                            break;
                        case MARKET_ACTIVITY:
                            marketActivityModel.deleteBatch(addDataIds, corpid);
                            marketActivityUserModel.batchDeleteByMarketActivityId(corpid, addDataIds, null);
                            break;
                        case SALES_OPPORTUNITY:
                            opportunityModel.deleteBatch(addDataIds, corpid);
                            opportunityUserModel.deleteBatchByOpportunityIdIn(addDataIds, corpid);
                            opportunityProductModel.deleteBatchByProductId(addDataIds, corpid);
                            break;
                        case OTHER_EXPENSE:
                            otherExpenseModel.deleteBatch(addDataIds, corpid);
                            break;
                        case OTHER_INCOME:
                            otherIncomeModel.deleteBatch(addDataIds, corpid);
                            break;
                        case OUTSTOCK:
                        case CONTRACT_OUTSTOCK:
                        case OTHER_OUTSTOCK:
                        case RETURNED_PURCHASE_OUTSTOCK:
                        case WORK_ORDER_OUTSTOCK:
                        case PRODUCTION_MATERIEL_OUTSTOCK:
                            outstockModel.deleteBatch(addDataIds, corpid);
                            outstockProductModel.deleteByOutstockIdIn(corpid, addDataIds);
                            break;
                        case PAYMENT:
                            break;
                        case PAYMENT_SHEET:
                        case WRITE_OFF_PREPAYMENT:
                        case PREPAYMENT:
                        case RED_PREPAYMENT:
                        case RED_PAYMENT_SHEET:
                        case RED_WRITE_OFF_PREPAYMENT:
                        case RED_WRITE_OFF_BALANCE:
                        case BAD_DEBT:
                            paymentSheetModel.deleteBatch(addDataIds, corpid, 0);
                            paymentSheetUserModel.deleteByPaymentSheetIds(addDataIds, corpid);
                            break;
                        case PAY_PLAN:
                            break;
                        case PAY_SHEET:
                        case WRITE_OFF_PREPAY:
                        case RED_WRITE_OFF_PAY:
                        case RED_WRITE_OFF_PREPAY:
                        case PREPAY:
                        case RED_PREPAY:
                        case BAD_PAY:
                            payPlanSheetModel.deleteBatch(addDataIds, corpid, 0);
                            payPlanSheetUserModel.deleteByPurchaseIdIn(addDataIds, corpid);
                            break;
                        case PRODUCT:
                            break;
                        case PRODUCTION_ORDER:
                            productionOrderModel.deleteBatch(addDataIds, corpid);
                            productionOrderUserModel.deleteByProOrderIdIn(addDataIds, corpid);
                            productionOrderProductModel.deleteByProOrderIdIn(addDataIds, corpid);
                            break;
                        case PURCHASE:
                            purchaseModel.deleteBatch(addDataIds, corpid);
                            purchaseUserModel.deletByDataIds(addDataIds, corpid);
                            purchaseProductModel.deleteByPurchaseIdIn(addDataIds, corpid);
                            break;
                        case PURCHASE_INVOICE:
                            purchaseInvoiceModel.deleteBatch(addDataIds, corpid);
                            break;
                        case QUOTATION:
                            quotationModel.deleteBatch(addDataIds, corpid);
                            quotationUserModel.deleteBatchByQuotationIdIn(addDataIds, corpid);
                            quotationProductModel.deleteQuotationAllProduct(addDataIds, corpid);
                            break;
                        case REFUND:
                            refundModel.deleteBatch(addDataIds, corpid, null);
                            refundUserModel.deleteBatchByRefundIdIn(addDataIds, corpid);
                            break;
                        case RETURNED_PURCHASE:
                            returnedPurchaseModel.deleteBatch(addDataIds, corpid);
                            returnedPurchaseProductModel.deleteByReturnPurchaseIdIn(addDataIds, corpid);
                            break;
                        case SUPPLIER_COMMUNICATE:
                            supplierCommunicateModel.deleteBatch(addDataIds, corpid);
                            break;
                        case SUPPLIER_CONTACT:
                            supplierContactModel.deleteBatch(addDataIds, corpid);
                            supplierContactUserModel.deleteByDataIds(addDataIds, corpid);
                            break;
                        case SUPPLIER:
                            supplierModel.deleteBatch(addDataIds, corpid);
                            supplierUserModel.deleteBySupplierIdIn(addDataIds, corpid);
                            break;
                        case TRANSFER:
                            transferModel.deleteBatch(addDataIds, corpid, null);
                            transferProductModel.deleteByTransferIds(addDataIds, corpid);
                            break;
                        case WAREHOUSE:
                            warehouseModel.deleteBatch(addDataIds, corpid);
                            warehouseUserModel.deleteByDataIds(addDataIds, corpid);
                            break;
                        case WORK_ORDER:
                            workOrderModel.deleteBatch(addDataIds, corpid);
                            workOrderFlowUserModel.batchDeleteByWorkOrderId(corpid, addDataIds, null);
                            workOrderProductModel.deleteByWorkOrderIdIn(addDataIds, corpid);
                            break;
                        case WORK_REPORT:
                            break;
                        default:
                    }
                } else {
                    paasFormDataModel.deleteBatch(addDataIds, corpid, 0);
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    public void workflowDataDelete(FixDataJobDTO fixDataJobDTO) throws XbbException {
        String corpid = fixDataJobDTO.getCorpid();
        List<Long> taskIds = fixDataJobDTO.getDataIdList();
        if (CollectionsUtil.isNotEmpty(taskIds)) {
            Map<String, Object> param = new HashMap<>();
            param.put(ParameterConstant.CORPID, corpid);
            param.put("idIn", taskIds);
            List<WorkflowTaskEntity> workflowTaskEntityList = workflowTaskModel.findEntities(param);

            if (CollectionsUtil.isNotEmpty(workflowTaskEntityList)) {
                Map<String, List<Long>> businessTypeAndDataIdsMap = new HashMap<>();
                workflowTaskEntityList.forEach(v -> businessTypeAndDataIdsMap.computeIfAbsent(v.getSaasMark() + "_" + v.getBusinessType(), i -> new ArrayList<>()).add(v.getDataId()));
                Map<String, List<Long>> businessTypeAndTaskIdsMap = new HashMap<>();
                workflowTaskEntityList.forEach(v -> businessTypeAndTaskIdsMap.computeIfAbsent(v.getSaasMark() + "_" + v.getBusinessType(), i -> new ArrayList<>()).add(v.getId()));

                for (Map.Entry<String, List<Long>> entry : businessTypeAndDataIdsMap.entrySet()) {
                    String key = entry.getKey();
                    List<Long> value = entry.getValue();
                    String[] strings = key.split("_");
                    log.warn(XbbRefTypeEnum.getByCode(Integer.valueOf(strings[1])).getName() + "工作流迁移数据开始还原, businessType= " + strings[1]);
                    if (Objects.equals(strings[0], SaasMarkEnum.SAAS.getCode().toString())) {
                        extracted(corpid, SaasMarkEnum.SAAS.getCode(), Integer.valueOf(strings[1]), businessTypeAndTaskIdsMap.get(key), value);
                    } else {
                        extracted(corpid, SaasMarkEnum.PAAS.getCode(), 0, businessTypeAndTaskIdsMap.get(key), value);
                    }
                }

            }

        }

        log.warn("工作流迁移数据还原结束，success");

    }

    public void workflowComment(FixDataJobDTO fixDataJobDTO) throws XbbException {
        String corpid = fixDataJobDTO.getCorpid();

        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        if (!Objects.isNull(fixDataJobDTO.getAddTimeStart())) {
            param.put("addTimeStart", fixDataJobDTO.getAddTimeStart());
        }

        Integer entitysCount = paasProcessDataMigrateModel.getEntitysCount(param);

        param.put("startGroup", 0);
        param.put("pageNumGroup", 100);
        Long idGte = 0L;

        log.warn("审批评论开始迁移");
        Long count = 0L;
        while (true) {
            param.put("idGte", idGte);
            List<PaasProcessDataMigrateEntity> processDataMigrateEntityList = paasProcessDataMigrateModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(processDataMigrateEntityList)) {
                break;
            }

            idGte = processDataMigrateEntityList.get(processDataMigrateEntityList.size() -1 ).getId();
            count = count + processDataMigrateEntityList.size();
            log.warn("审批评论迁移进度，total=" + entitysCount + ", now=" + count);

            List<Long> processTaskIds = new ArrayList<>();
            Map<Long, Long> processTaskIdAndWorkflowTaskIdMap = new HashMap<>();
            processDataMigrateEntityList.forEach(v ->
                    {
                        if (!Objects.equals(v.getWorkflowTaskId(), 0L)) {
                            processTaskIdAndWorkflowTaskIdMap.put(v.getProcessTaskId(), v.getWorkflowTaskId());
                            processTaskIds.add(v.getProcessTaskId());
                        }
                    }
            );

            Map<String, Object> params = new HashMap<>();
            params.put(ParameterConstant.CORPID, corpid);
            params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            params.put("type", BusinessCommentEnum.APPROVAL.getCode());
            params.put("refIdIn", processTaskIds);
            List<PaasCommentEntityExt> commentEntityExts = paasCommentModel.list(params);

            List<WorkflowCommentEntity> insertList = new ArrayList<>();
            for (PaasCommentEntityExt commentEntityExt : commentEntityExts) {


                Long taskId = processTaskIdAndWorkflowTaskIdMap.get(commentEntityExt.getRefId());
                if (Objects.isNull(taskId)) {
                    continue;
                }
                WorkflowCommentEntity workflowCommentEntity = new WorkflowCommentEntity();
                workflowCommentEntity.setCorpid(commentEntityExt.getCorpid());
                workflowCommentEntity.setAppId(commentEntityExt.getAppId());
                workflowCommentEntity.setRefId(taskId);
                workflowCommentEntity.setUserId(commentEntityExt.getUserId());
                workflowCommentEntity.setUserName(commentEntityExt.getUserName());
                workflowCommentEntity.setUserAvatar(commentEntityExt.getUserAvatar());
                workflowCommentEntity.setRefUserId(commentEntityExt.getRefUserId());
                workflowCommentEntity.setRefUserName(commentEntityExt.getRefUserName());
                workflowCommentEntity.setAtUserId(commentEntityExt.getAtUserId());
                workflowCommentEntity.setContent(commentEntityExt.getContent());
                workflowCommentEntity.setImage(commentEntityExt.getImage());
                workflowCommentEntity.setAttachment(commentEntityExt.getAttachment());
                workflowCommentEntity.setAddTime(commentEntityExt.getAddTime());
                workflowCommentEntity.setUpdateTime(commentEntityExt.getUpdateTime());
                workflowCommentEntity.setDel(commentEntityExt.getDel());

                insertList.add(workflowCommentEntity);
            }

            if (CollectionsUtil.isNotEmpty(insertList)) {
                workflowCommentModel.insertBatch(insertList);
            }


        }

        log.warn("审批评论迁移完成");

    }
}
